package com.hoodemia.core;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.microedition.io.Connector;
import javax.microedition.io.HttpConnection;

import net.rim.device.api.servicebook.ServiceBook;
import net.rim.device.api.servicebook.ServiceRecord;
import net.rim.device.api.system.CoverageInfo;
import net.rim.device.api.system.DeviceInfo;
import net.rim.device.api.system.WLANInfo;

import org.json.me.JSONArray;
import org.json.me.JSONException;

import com.Localytics.LocalyticsSession.UploaderThread;

public final class WebServiceHandler {
	private static final String urlPrefix = "https://hoodemia.com/mws/service.php?";

	private WebServiceHandler () { }
	private static final WebServiceHandler instance = new WebServiceHandler();
	public static WebServiceHandler getInstance () { return instance; }
	private JSONArray method (String act, String theRest) throws IOException, JSONException
	{
		// add(new RichTextField("masuk?"));
		HttpConnection conn = (HttpConnection) Connector.open(urlPrefix
				+ "act=" + act + theRest
				+ "&bb=" + getConnectionString());
		// HttpConnection conn = (HttpConnection)
		// Connector.open("http://google.com"+getConnectionString());
		// add(new RichTextField("Bisa? 1: "+conn.getURL()));
		InputStream is = null;
		is = conn.openInputStream();
		// add(new RichTextField("Bisa? 2 length: "+ conn.getLength() + ", " +
		// conn.getResponseCode()+ ", " + conn.hashCode() + ", " + conn.getURL()
		// + ", " +
		// " is length = "+is.toString()+", "+is.hashCode()+", "+is.available()+", "));
		// add(new RichTextField(conn.toString()));
		int len = (int) conn.getLength();
		byte[] data;
		if (len > 0) {
			// If the response has a Content-Length...
			int actual = 0;
			int bytesread = 0;
			data = new byte[len];
			while ((bytesread != len) && (actual != -1)) {
				actual = is.read(data, bytesread, len - bytesread);
				bytesread += actual;
			}

		} else {
			// The response doesn't have a Content-Length...
			int ch;
			ByteArrayOutputStream o = new ByteArrayOutputStream();
			len = 0;
			while ((ch = is.read()) != -1) {
				o.write(ch);
				++len;
			}
			data = o.toByteArray();
		}

		String id = new String(data);

		return new JSONArray(id);
	}
	
	public JSONArray SignUp(String username, String password, String confirmPassword, String email) throws IOException, JSONException {
		return method("SignUp", "&uname=" + username + "&newpass=" + password + "&cnewpass=" + confirmPassword + "&email=" + email);
	}
	
	/*
	//FUNCTION CODE: Ax
	//webservice access for login
	public JSONArray A1(String username, String password) throws IOException, JSONException {
		return method("A1", "&uname=" + username + "&pass=" + password);
	}
	
	//webservice access for user profile
	public JSONArray A3(int uid) throws IOException, JSONException {
		return method("A3", "&uid=" + uid);
	}
	
	//webservice access for password change
	public JSONArray A5(int uid, String oldpass, String newpass, String cnewpass) throws IOException, JSONException {
		return method("A5", "&uid=" + uid + "&oldpass=" + oldpass + "&newpass=" + newpass + "&cnewpass=" + cnewpass);
	}
	
	//FUNCTION CODE: Bx
	//webservice access for retrieving all feeds
	public JSONArray B1(int uid) throws IOException, JSONException {
		return method("B1", "&uid=" + uid);
	}
	
	//webservice access for retrieving own feeds
	public JSONArray B2(int uid) throws IOException, JSONException {
		return method("B2", "&uid=" + uid);
	}
	
	//webservice access for posting feeds
	public JSONArray B3(int uid, int feedid, String comment) throws IOException, JSONException {
		return method("B3", "&uid=" + uid + "&feedid=" + feedid + "&comment=" + comment);
	}
	
	//webservice access for like a feed
	public JSONArray B4(int uid, int feedid) throws IOException, JSONException {
		return method("B4", "&uid=" + uid + "&feedid=" + feedid);
	}
	
	//webservice access for comment a feed
	public JSONArray B5(int uid, int feedid, String comment) throws IOException, JSONException {
		return method("B5", "&uid=" + uid + "&feedid=" + feedid + "&comment=" + comment);
	}
	
	//webservice access for hide a feed
	public JSONArray B6(int uid, int feedid) throws IOException, JSONException {
		return method("B6", "&uid=" + uid + "&feedid=" + feedid);
	}
	
	//webservice access for retrieving comments from a feed
	public JSONArray B7(int uid, int feedid) throws IOException, JSONException {
		return method("B7", "&uid=" + uid + "&feedid=" + feedid);
	}
	
	//webservice access for unlike a feed
	public JSONArray B8(int uid, int feedid) throws IOException, JSONException {
		return method("B8", "&uid=" + uid + "&feedid=" + feedid);
	}
	
	//webservice access for retrieving people who likes a feed
	public JSONArray B9(int feedid) throws IOException, JSONException {
		return method("B9", "&feedid=" + feedid);
	}
	
	//FUNCTION CODE: Cx
	//webservice access for add friend
	public JSONArray C1(int uid, int friendid, String message) throws IOException, JSONException {
		return method("C1", "&uid=" + uid + "&friendid=" + friendid + "&message=" + message);
	}
	
	//webservice access for remove friend
	public JSONArray C2(int uid, int friendid) throws IOException, JSONException {
		return method("C2", "&uid=" + uid + "&friendid=" + friendid);
	}
	
	//C3 = follow user
	//C4 = unfollow user
	
	//webservice access for approve friend request
	public JSONArray C5(int uid, int friendid) throws IOException, JSONException {
		return method("C5", "&uid=" + uid + "&friendid=" + friendid);
	}
	
	//webservice access for remove friend request
	public JSONArray C6(int uid, int friendid) throws IOException, JSONException {
		return method("C6", "&uid=" + uid + "&friendid=" + friendid);
	}
	
	//webservice access for block user
	public JSONArray C7(int uid, int friendid) throws IOException, JSONException {
		return method("C7", "&uid=" + uid + "&friendid=" + friendid);
	}
	
	//webservice access for unblock user
	public JSONArray C8(int uid, int friendid) throws IOException, JSONException {
		return method("C8", "&uid=" + uid + "&friendid=" + friendid);
	}
	
	//webservice access for browse friend that user uid have
	public JSONArray C9(int uid, String msg) throws IOException, JSONException {
		return method("C9", "&uid=" + uid + "&msg=" + msg);
	}
	
	//webservice access for check some user is a friend or not
	public JSONArray C10(int uid, int friendid) throws IOException, JSONException {
		return method("C10", "&uid=" + uid + "&friendid=" + friendid);
	}
	
	//webservice access for retrieving friend request
	public JSONArray C11(int uid) throws IOException, JSONException {
		return method("C11", "&uid=" + uid);
	}
	
	//FUNCTION CODE: Ux
	//webservice access for user friends
	public JSONArray U3(int uid) throws IOException, JSONException {
		return method("U3", "&uid=" + uid);
	}
	
	//FUNCTION CODE: Mx
	//webservice access for user unread messages
	public JSONArray M2(int uid) throws IOException, JSONException {
		return method("M2", "&uid=" + uid);
	}
	
	//FUNCTION CODE: Dx
	
	//D1 = setting notification
	
	//webservice access for mark as read notification
	public JSONArray D2(int uid, int notifid) throws IOException, JSONException {
		return method("D2", "&uid=" + uid + "&notifid=" + notifid);
	}
	
	//webservice access for list of unread notification
	public JSONArray D3(int uid) throws IOException, JSONException {
		return method("D3", "&uid=" + uid);
	}
	
	//webservice access for list of readed notification
	public JSONArray D4(int uid) throws IOException, JSONException {
		return method("D4", "&uid=" + uid);
	}
	
	//webservice access for num of unread notification
	public JSONArray D5(int uid) throws IOException, JSONException {
		return method("D5", "&uid=" + uid);
	}
	
	//FUNCTION CODE: Ex
	//webservice access for retrieving academic institution info
	public JSONArray E1(int uid) throws IOException, JSONException {
		return method("E1", "&uid=" + uid);
	}
	
	//webservice access for retrieving user academic info
	public JSONArray E2(int uid, int instid) throws IOException, JSONException {
		return method("E2", "&uid=" + uid + "&iid=" + instid);
	}
	
	//webservice access for retrieving user academic history
	public JSONArray E3(int uid, int instid) throws IOException, JSONException {
		return method("E3", "&uid=" + uid + "&iid=" + instid);
	}
	
	//webservice access for retrieving user academic timetable
	public JSONArray E4(int uid, int instid) throws IOException, JSONException {
		return method("E4", "&uid=" + uid + "&iid=" + instid);
	}
	
	//FUNCTION CODE: Fx
	//webservice access for checking user like the feed or not
	public JSONArray F1(int uid, int streamid) throws IOException, JSONException {
		return method("F1", "&uid=" + uid + "&streamid=" + streamid);
	}
	
	//webservice access for checking user hide the feed or not
	public JSONArray F2(int uid, int streamid) throws IOException, JSONException {
		return method("F2", "&uid=" + uid + "&streamid=" + streamid);
	}
	
	//webservice access for checking user block the feed or not
	public JSONArray F3(int uid, int streamid) throws IOException, JSONException {
		return method("F3", "&uid=" + uid + "&streamid=" + streamid);
	}
	
	//FUNCTION CODE: Gx
	//webservice access for retrieving academic institution info
	public JSONArray G0(int uid) throws IOException, JSONException {
		return method("G0", "&uid=" + uid);
	}
	
	//webservice access for retrieving user academic info
	public JSONArray G1(int uid, int instid) throws IOException, JSONException {
		return method("G1", "&uid=" + uid + "&iid=" + instid);
	}
	
	//webservice access for retrieving user academic history per term
	public JSONArray G2(int uid, int instid) throws IOException, JSONException {
		return method("G2", "&uid=" + uid + "&iid=" + instid);
	}
	
	//webservice access for retrieving user academic history per course
	public JSONArray G3(int uid, int instid) throws IOException, JSONException {
		return method("G3", "&uid=" + uid + "&iid=" + instid);
	}
	
	//webservice access for retrieving user academic events
	public JSONArray G4(int uid, int instid) throws IOException, JSONException {
		return method("G4", "&uid=" + uid + "&iid=" + instid);
	}
	
	//webservice access for retrieving user academic timetable
	public JSONArray G5(int uid, int instid) throws IOException, JSONException {
		return method("G5", "&uid=" + uid + "&iid=" + instid);
	}
	
	//webservice access for retrieving user academic message
	public JSONArray G6(int uid, int instid) throws IOException, JSONException {
		return method("G6", "&uid=" + uid + "&iid=" + instid);
	}
	
	//webservice access for sending message to academic advisor
	public JSONArray G7(int uid, int instid, String msg) throws IOException, JSONException {
		return method("G7", "&uid=" + uid + "&iid=" + instid + "&msg=" + msg);
	}
	
	//FUNCTION CODE: MDx
	//webservice access for retrieving list forum of moodle
	public JSONArray MD1(int uid, int aid) throws IOException, JSONException {
		return method("MD1", "&uid=" + uid + "&aid=" + aid);
	}
	
	//webservice access for retrieving list thread of moodle
	public JSONArray MD2(int uid, int forumid, int paging, int aid) throws IOException, JSONException {
		return method("MD2", "&uid=" + uid + "&forumid=" + forumid + "&paging=" + paging + "&aid=" + aid);
	}
	
	//webservice access for retrieving list post id of moodle
	public JSONArray MD3(int uid, int discid, int aid) throws IOException, JSONException {
		return method("MD3", "&uid=" + uid + "&discid=" + discid + "&aid=" + aid);
	}
	
	//webservice access for displaying post of moodle
	public JSONArray MD4(int uid, int aid, int discid, int parentid) throws IOException, JSONException {
		return method("MD4", "&uid=" + uid + "&aid=" + aid + "&discid=" + discid + "&parentid=" + parentid);
	}
	
	//webservice access for reply post to moodle
	public JSONArray MD5(int uid,  int parentid, String subject, String msg, int aid) throws IOException, JSONException {
		return method("MD5", "&uid=" + uid + "&parentid=" + parentid + "&subject=" + subject + "&msg=" + msg + "&aid=" + aid );
	}
	
	//FUNCTION CODE: CFx
	//webservice access for retrieving list of custom feed
	public JSONArray CF1(int uid) throws IOException, JSONException {
		return method("CF1", "&uid=" + uid);
	}
	
	//webservice access for retrieving list of custom feed
	public JSONArray CF2(int uid) throws IOException, JSONException {
		return method("CF2", "&uid=" + uid);
	}
	
	//FUNCTION CODE: MEx
	//webservice access for retrieving inbox
	public JSONArray ME1(int toid) throws IOException, JSONException {
		return method("ME1", "&toid=" + toid);
	}

	//webservice access for retrieving outbox
	public JSONArray ME2(int fromid) throws IOException, JSONException {
		return method("ME2", "&fromid=" + fromid);
	}
	
	//webservice access for retrieving incoming message
	public JSONArray ME3(int mid) throws IOException, JSONException {
		return method("ME3", "&mid=" + mid);
	}
	
	//webservice access for create new message
	public JSONArray ME4(int fromid, int toid, String subject, String msg) throws IOException, JSONException {
		return method("ME4", "&fromid=" + fromid + "&toid=" + toid + "&subject=" + subject + "&msg=" + msg );
	}
	*/

	public static String getConnectionString() {
		// This code is based on the connection code developed by Mike Nelson of
		// AccelGolf.
		// http://blog.accelgolf.com/2009/05/22/blackberry-cross-carrier-and-cross-network-http-connection
		String connectionString = null;

		// Simulator behavior is controlled by the USE_MDS_IN_SIMULATOR
		// variable.
		if (DeviceInfo.isSimulator()) {
			if (UploaderThread.USE_MDS_IN_SIMULATOR) {
				UploaderThread
						.logMessage("Device is a simulator and USE_MDS_IN_SIMULATOR is true");
				connectionString = ";deviceside=false";
			} else {
				UploaderThread
						.logMessage("Device is a simulator and USE_MDS_IN_SIMULATOR is false");
				connectionString = ";deviceside=true";
			}
		}

		// Wifi is the preferred transmission method
		else if (WLANInfo.getWLANState() == WLANInfo.WLAN_STATE_CONNECTED) {
			UploaderThread.logMessage("Device is connected via Wifi.");
			connectionString = ";interface=wifi";
		}

		// Is the carrier network the only way to connect?
		else if ((CoverageInfo.getCoverageStatus() & CoverageInfo.COVERAGE_DIRECT) == CoverageInfo.COVERAGE_DIRECT) {
			UploaderThread.logMessage("Carrier coverage.");

			String carrierUid = getCarrierBIBSUid();		// THIS METHOD REQUIRE SIGNING
			if (carrierUid == null) {
				// Has carrier coverage, but not BIBS. So use the carrier's TCP
				// network
				UploaderThread.logMessage("No Uid");
				connectionString = ";deviceside=true";
			} else {
				// otherwise, use the Uid to construct a valid carrier BIBS
				// request
				UploaderThread.logMessage("uid is: " + carrierUid);
				connectionString = ";deviceside=false;connectionUID="
						+ carrierUid + ";ConnectionType=mds-public";
			}
		}

		// Check for an MDS connection instead (BlackBerry Enterprise Server)
		else if ((CoverageInfo.getCoverageStatus() & CoverageInfo.COVERAGE_MDS) == CoverageInfo.COVERAGE_MDS) {
			UploaderThread.logMessage("MDS coverage found");
			connectionString = ";deviceside=false";
		}

		// If there is no connection available abort to avoid bugging the user
		// unnecssarily.
		else if (CoverageInfo.getCoverageStatus() == CoverageInfo.COVERAGE_NONE) {
			UploaderThread.logMessage("There is no available connection.");
		}

		// In theory, all bases are covered so this shouldn't be reachable.
		else {
			UploaderThread
					.logMessage("no other options found, assuming device.");
			connectionString = ";deviceside=true";
		}

		return connectionString;
	}

	// FIXME app need to be signed to make this function could run on device
	/**
	 * Looks through the phone's service book for a carrier provided BIBS
	 * network
	 * 
	 * @return The uid used to connect to that network.
	 */
	private static String getCarrierBIBSUid() {
		ServiceRecord[] records = ServiceBook.getSB().getRecords();
		int currentRecord;

		for (currentRecord = 0; currentRecord < records.length; currentRecord++) {
			if (records[currentRecord].getCid().toLowerCase().equals("ippp")) {
				if (records[currentRecord].getName().toLowerCase().indexOf(
						"bibs") >= 0) {
					return records[currentRecord].getUid();
				}
			}
		}

		return null;
	}
}
